<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket-TCP Proxy Client</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            background: linear-gradient(120deg, #f3f4f6, #e5e7eb);
        }
        #container {
            width: 90%;
            margin: 20px auto;
            max-width: 800px;
            background: #ffffff;
            border-radius: 12px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            padding: 20px;
        }
        #messages {
            height: 300px;
            overflow-y: auto;
            background: #f9fafb;
            border: 1px solid #e5e7eb;
            padding: 10px;
            margin-bottom: 20px;
            border-radius: 8px;
            display: flex;
            flex-direction: column;
        }
        .message {
            margin-bottom: 10px;
            padding: 10px;
            border-radius: 8px;
            font-size: 14px;
            position: relative;
            display: inline-block;
            max-width: 80%;
        }
        .message.me {
            background-color: #d1ecf1;
            text-align: left;
            align-self: flex-end;
        }
        .message.system {
            background-color: #e2e3e5;
            text-align: center;
            align-self: center;
            font-size: 12px;
            color: #6c757d;
        }
        .message.heartbeat {
            background-color: #f1f1f1;
            color: #a5a5a5;
            text-align: center;
            align-self: center;
            font-size: 12px;
        }
        .message.server {
            background-color: #d4edda;
            text-align: left;
            align-self: flex-start;
        }
        .timestamp {
            font-size: 10px;
            color: #6c757d;
            position: absolute;
            bottom: -18px;
            right: 10px;
        }
        #input-container {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
        }
        #input-container input,
        #input-container button {
            padding: 10px;
            font-size: 16px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        #input-container input {
            flex: 1;
        }
        #input-container button {
            background-color: #007bff;
            color: white;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        #input-container button:hover {
            background-color: #0056b3;
        }
        .button-group {
            display: flex;
            justify-content: space-between;
        }
        .connection-status {
            font-size: 12px;
            color: #6c757d;
            text-align: center;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
<div id="container">
    <h1 style="text-align: center; color: #333;">WebSocket-TCP Proxy Client</h1>
    <div id="messages"></div>
    <div class="connection-status">
        <span>状态: <span id="status-text">连接已关闭</span></span>
        <span class="user-info" id="user-info">用户ID: 未登录</span>
    </div>
    <div id="input-container">
        <input type="number" id="receiver-id" placeholder="请输入接收方ID">
        <input type="text" id="message" placeholder="请输入消息内容">
        <button id="send">发送</button>
    </div>
</div>

<script>
    document.addEventListener("DOMContentLoaded", () => {
        const serverUrl = "ws://127.0.0.1:8080"; // WebSocket 代理服务器地址
        const ws = new WebSocket(serverUrl);

        let userId = null;
        let heartbeatInterval = null;

        const MESSAGE_TYPES = {
            LOGIN: 0,
            HEART_BEAT: 1,
            SEND_MESSAGE: 3,
        };

        ws.onopen = () => {
            console.log("Connected to WebSocket server");
            updateConnectionStatus("状态: 已连接", "#28a745");

            userId = prompt("请输入您的用户ID:");
            if (userId) {
                sendJsonMessage({
                    sender_id: parseInt(userId),
                    receiver_id: null,
                    message_type: MESSAGE_TYPES.LOGIN,
                    context: "login request"
                });
                document.getElementById("user-info").textContent = `用户ID: ${userId}`;
                startHeartbeat();
            }
        };

        ws.onmessage = (event) => {
            try {
                const data = JSON.parse(event.data);
                console.log("Received:", data);

                const currentTime = new Date().toLocaleString();

                if (data.message_type === MESSAGE_TYPES.HEART_BEAT) {
                    displayMessage("心跳响应成功", "heartbeat", currentTime);
                } else if (data.message_type === MESSAGE_TYPES.SEND_MESSAGE) {
                    const { sender_id, context } = data;
                    displayMessage(`[用户 ${sender_id}] 发送的消息: ${context}`, "server", currentTime);
                }
                else  displayMessage("收到服务器响应: " + JSON.stringify(data), "server", currentTime);

            } catch (error) {
                console.error("Error processing received message:", error);
                displayMessage("消息解析失败: " + error.message, "system");
            }
        };

        ws.onerror = (error) => {
            console.error("WebSocket error:", error);
            updateConnectionStatus("状态: 连接错误", "#dc3545");
            displayMessage("连接错误", "system");
        };

        ws.onclose = () => {
            console.log("WebSocket connection closed");
            updateConnectionStatus("状态: 连接已关闭", "#6c757d");
            displayMessage("连接已关闭", "system");
            stopHeartbeat();
        };

        document.getElementById("send").addEventListener("click", () => {
            const messageInput = document.getElementById("message");
            const receiverIdInput = document.getElementById("receiver-id");
            const messageText = messageInput.value.trim();
            const receiverId = receiverIdInput.value.trim();

            if (messageText && receiverId && ws.readyState === WebSocket.OPEN) {
                const message = {
                    sender_id: parseInt(userId),
                    receiver_id: parseInt(receiverId),
                    message_type: MESSAGE_TYPES.SEND_MESSAGE,
                    context: messageText
                };
                sendJsonMessage(message);
                displayMessage(`[我] 发送给 [用户 ${receiverId}] 的消息: ${messageText}`, "me", new Date().toLocaleString());
                messageInput.value = "";
            } else {
                alert("请输入接收方ID和消息内容！");
            }
        });

        function startHeartbeat() {
            if (heartbeatInterval) return;
            heartbeatInterval = setInterval(() => {
                if (ws.readyState === WebSocket.OPEN) {
                    sendJsonMessage({
                        sender_id: parseInt(userId),
                        receiver_id: null,
                        message_type: MESSAGE_TYPES.HEART_BEAT,
                        context: "heartbeat"
                    });
                    displayMessage("已发送心跳包", "heartbeat", new Date().toLocaleString());
                }
            }, 10000);
        }

        function stopHeartbeat() {
            if (heartbeatInterval) {
                clearInterval(heartbeatInterval);
                heartbeatInterval = null;
            }
        }

        function displayMessage(text, type, timestamp = null) {
            const messagesDiv = document.getElementById("messages");
            const messageDiv = document.createElement("div");
            messageDiv.className = `message ${type}`;
            messageDiv.textContent = text;

            if (timestamp) {
                const timestampSpan = document.createElement("span");
                timestampSpan.className = "timestamp";
                timestampSpan.textContent = timestamp;
                messageDiv.appendChild(timestampSpan);
            }

            messagesDiv.appendChild(messageDiv);
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
        }

        function sendJsonMessage(message) {
            if (ws.readyState !== WebSocket.OPEN) {
                console.error("WebSocket connection is not open");
                return;
            }
            ws.send(JSON.stringify(message));
        }

        function updateConnectionStatus(statusText, color) {
            const statusDiv = document.getElementById("status-text");
            statusDiv.textContent = statusText;
            statusDiv.style.color = color;
        }
    });
</script>
</body>
</html>